home *** CD-ROM | disk | FTP | other *** search
/ HyperLib 1997 Winter - Disc 1 / HYPERLIB-1997-Winter-CD1.ISO.7z / HYPERLIB-1997-Winter-CD1.ISO / オンラインウェア / UTIL / Acme Filters 2.3.2 folder.sit / Acme Filters 2.3.2 folder / Acme Filters 2.3.2 / Acme Filters オ / Sources / Acme Filters.c < prev    next >
C/C++ Source or Header  |  1996-03-02  |  33KB  |  1,237 lines

  1. /**********************************************************************************************
  2.  * Program Name:  Acme Filters
  3.  *
  4.  * Module Name:   Acme Filters.c
  5.  *
  6.  * Description:   Convert Donna's word processor files to Mac files.
  7.  *
  8.  * Author:        Eric V. Curtis
  9.  *
  10.  * History:
  11.  *        v1.0.0  08-Mar-1995  Created.
  12.  *        v1.1.0  09-Mar-1995  Added old-style drag & drop processing of text files.
  13.  *        v1.2.0  22-Mar-1995  Added rot13 support, Cancel(), and SpinCursor().
  14.  *        v1.3.0  24-Mar-1995  Added the ability to set default translator via app name.
  15.  *        v1.3.1  28-Mar-1995  Updated SpinCursor() to not rely on specific resource ids.
  16.  *        v1.3.2  31-Mar-1995  Added check for max output filename length.
  17.  *        v1.4.0  11-Apr-1995  Added DeleteRF() and Touch().
  18.  *        v1.5.0  25-Apr-1995  Added TickleParentDir(), ScrollIcon(), and Progress().
  19.  *        v1.6.0  01-Jun-1995  Added basic apple event support.
  20.  *        v1.7.0  13-Jun-1995  Added GetFileOSType() and the ability to Touch any file.
  21.  *        v1.7.1  15-Jun-1995  Added splash screen on kAEOpenApplication event, adjusted how
  22.  *                             gAutoQuit works, and made the progress bar black & white.
  23.  *        v1.8.0  16-Jun-1995  Added TypeCreator() and related routines.
  24.  *        v1.8.1  18-Jun-1995  Added better handling of filename conflicts.
  25.  *        v1.9.0  25-Jun-1995  Added the ability to select a filter at the time files are
  26.  *                             dragged to the app (when the option key is held down).
  27.  *        v1.9.1  30-Jun-1995  Touch() now always sets seconds to zero.
  28.  *        v2.0.0  01-Jul-1995  Renamed to Acme Filters.  Added Tab2Space().
  29.  *        v2.0.1  28-Jul-1995  Rewrote Rot13() algorithm.
  30.  *        v2.1.0  12-Oct-1995  Rot13() and Tab2Space() now replace the original file instead
  31.  *                             of creating a duplicate with .r13 or .t2s suffixes.  Default
  32.  *                             filter can now be set via the keyboard (1 thru 6).  Cancel
  33.  *                             requests are now handled more reliably.
  34.  *        v2.2.0  03-Nov-1995  Added MacDosUnix() and related routines.
  35.  *        v2.2.2  16-Nov-1995  Touch() can now specify creation and modification dates.
  36.  *                             Removed MacDosUnix() because I couldn't get it to work right.
  37.  *        v2.3.0  02-Feb-1996  Progress window is now movable-modal and its position is
  38.  *                             saved and restored between launches.  Added FindOriginal().
  39.  *        v2.3.1  12-Feb-1996  Improved progress window updating.  Rewrote FindOriginal().
  40.  *        v2.3.2  16-Feb-1996  FindOriginal() now also handles folders.
  41.  *
  42.  * Functions:     main()
  43.  *                GetOurProcessInfo()
  44.  *                SetupMenuBar()
  45.  *                HandleEvent()
  46.  *                HandleKeyDown()
  47.  *                HandleMouseDown()
  48.  *                HandleMenuChoice()
  49.  *                HandleAppleMenu()
  50.  *                HandleFileMenu()
  51.  *                GetFileSpec()
  52.  *                FSpfopen()
  53.  *                TickleParentDir()
  54.  *                GetFileOSType()
  55.  *                GetFSSpecType()
  56.  *                AboutBox()
  57.  *                AboutBoxDlgFltr()
  58.  *                CenterString()
  59.  *                pstrcat()
  60.  *                pstrcpy()
  61.  *                Cancel()
  62.  *                SpinCursor()
  63.  *                ScrollIcon()
  64.  *                Progress()
  65.  *                FrameBar()
  66.  *                LoadWindowPrefs()
  67.  *                SaveWindowPrefs()
  68.  *                ChooseDefault()
  69.  *                ChooseDefaultDlgFltr()
  70.  *                LoadFilterPrefs()
  71.  *                SaveFilterPrefs()
  72.  *                SpecialKeyDown()
  73.  **********************************************************************************************/
  74.  
  75.  
  76.  
  77. /************ I N C L U D E   F I L E S *******************************************************/
  78.  
  79. #include <stdio.h>
  80. #include <string.h>
  81. #include <Files.h>
  82. #include <Icons.h>
  83.  
  84. #include "Acme Filters.h"
  85. #include "Acme Filters AE.h"
  86. #include "ASCToMac.h"
  87. #include "Delete RF.h"
  88. #include "FindOriginal.h"
  89. #include "Rot13.h"
  90. #include "Tab2Space.h"
  91. #include "Touch.h"
  92. #include "TypeCreator.h"
  93.  
  94.  
  95.  
  96. /************ G L O B A L   V A R I A B L E S *************************************************/
  97.  
  98. Str32        gAppName;
  99. MenuHandle    gAppleMenu, gFileMenu;
  100. char        gConversionType;
  101. Boolean        gQuit = false, gAutoQuit = true;
  102. DialogPtr    gProgressDlog = (DialogPtr)0L;
  103. Boolean        gFromMenu = false;
  104. Boolean        gCancelReq;
  105.  
  106.  
  107.  
  108. /**********************************************************************************************
  109.  * Function Name:  main
  110.  *
  111.  * Description:    Standard stuff.
  112.  *
  113.  * Parameters:     None.
  114.  *
  115.  * Return Value:   None.
  116.  **********************************************************************************************/
  117. void    main( void )
  118. {
  119.     EventRecord    event;
  120.     
  121.     InitGraf( &qd.thePort );
  122.     InitFonts();
  123.     FlushEvents( everyEvent, 0 );
  124.     InitWindows();
  125.     InitMenus();
  126.     TEInit();
  127.     InitDialogs( 0 );
  128.     InitCursor();
  129.     
  130.     GetOurProcessInfo();
  131.     SetupMenuBar();
  132.     InstallAEHandlers();
  133.     
  134.     while ( !gQuit )
  135.     {
  136.         SetCursor( &qd.arrow );
  137.         HandleEvent( &event );
  138.     }
  139. }
  140.  
  141.  
  142.  
  143. /**********************************************************************************************
  144.  * Function Name:  GetOurProcessInfo
  145.  *
  146.  * Description:    Get our app's name.
  147.  *
  148.  * Parameters:     None.
  149.  *
  150.  * Return Value:   None.
  151.  **********************************************************************************************/
  152. void    GetOurProcessInfo( void )
  153. {
  154.     OSErr                err;
  155.     long                response;
  156.     ProcessSerialNumber    psn;
  157.     ProcessInfoRec        info;
  158.     FSSpec                fsp;
  159.     
  160.     // this app requires system 7 or above
  161.     err = Gestalt( gestaltSystemVersion, &response );
  162.     if ( err || ((response & 0xFFFF) < kSystemSeven) )
  163.     {
  164.         SysBeep( 1 );
  165.         ExitToShell();
  166.     }
  167.     
  168.     // get our app's name
  169.     GetCurrentProcess( &psn );
  170.     info.processInfoLength = sizeof( ProcessInfoRec );
  171.     info.processName = gAppName;
  172.     info.processAppSpec = &fsp;
  173.     GetProcessInformation( &psn, &info );
  174.     
  175.     // load the default conversion type
  176.     gConversionType = LoadFilterPrefs();
  177. }
  178.  
  179.  
  180.  
  181. /**********************************************************************************************
  182.  * Function Name:  SetupMenuBar
  183.  *
  184.  * Description:    Standard stuff.
  185.  *
  186.  * Parameters:     None.
  187.  *
  188.  * Return Value:   None.
  189.  **********************************************************************************************/
  190. void    SetupMenuBar( void )
  191. {
  192.     short    i;
  193.     Str255    aboutStr;
  194.     
  195.     SetMenuBar( GetNewMBar( kBaseResID ) );
  196.     gAppleMenu = GetMHandle( kAppleMenuID );
  197.     gFileMenu = GetMHandle( kFileMenuID );
  198.     
  199.     // give the filters command-key equivalents
  200.     for ( i = kASCToMac; i <= kTypeCreator; i++ )
  201.         SetItemCmd( gFileMenu, i, i+'0' );
  202.     
  203.     // put our app's name in the about menu
  204.     pstrcpy( aboutStr, "¥pAbout " );
  205.     pstrcat( aboutStr, gAppName );
  206.     pstrcat( aboutStr, "¥pノ" );
  207.     SetItem( gAppleMenu, kAboutItem, aboutStr );
  208.     
  209.     AddResMenu( gAppleMenu, 'DRVR' );
  210.     DrawMenuBar();
  211. }
  212.  
  213.  
  214.  
  215. /**********************************************************************************************
  216.  * Function Name:  HandleEvent
  217.  *
  218.  * Description:    Standard stuff.
  219.  *
  220.  * Parameters:     event - the event record to process.
  221.  *
  222.  * Return Value:   None.
  223.  **********************************************************************************************/
  224. void    HandleEvent( EventRecord *event )
  225. {
  226.     WaitNextEvent( everyEvent, event, 15L, nil );
  227.     
  228.     switch ( event->what )
  229.     {
  230.         case keyDown:
  231.             HandleKeyDown( event );
  232.             break;
  233.         
  234.         case mouseDown:
  235.             HandleMouseDown( event );
  236.             break;
  237.         
  238.         case kHighLevelEvent:
  239.             AEProcessAppleEvent( event );
  240.             break;
  241.     }
  242. }
  243.  
  244.  
  245.  
  246. /**********************************************************************************************
  247.  * Function Name:  HandleKeyDown
  248.  *
  249.  * Description:    Standard stuff.
  250.  *
  251.  * Parameters:     event - the event record.
  252.  *
  253.  * Return Value:   None.
  254.  **********************************************************************************************/
  255. void    HandleKeyDown( EventRecord *event )
  256. {
  257.     if ( (event->modifiers & cmdKey) )
  258.     {
  259.         HandleMenuChoice( MenuKey( event->message & charCodeMask ) );
  260.     }
  261. }
  262.  
  263.  
  264.  
  265. /**********************************************************************************************
  266.  * Function Name:  HandleMouseDown
  267.  *
  268.  * Description:    Standard stuff.
  269.  *
  270.  * Parameters:     event - the event record.
  271.  *
  272.  * Return Value:   None.
  273.  **********************************************************************************************/
  274. void    HandleMouseDown( EventRecord *event )
  275. {
  276.     WindowPtr    whichWindow;
  277.     
  278.     switch ( FindWindow( event->where, &whichWindow ) )
  279.     {
  280.         case inMenuBar:
  281.             HandleMenuChoice( MenuSelect( event->where ) );
  282.             break;
  283.     }
  284. }
  285.  
  286.  
  287.  
  288. /**********************************************************************************************
  289.  * Function Name:  HandleMenuChoice
  290.  *
  291.  * Description:    Standard stuff.
  292.  *
  293.  * Parameters:     choice - hi word contains menu number, lo word contains menu item.
  294.  *
  295.  * Return Value:   None.
  296.  **********************************************************************************************/
  297. void    HandleMenuChoice( long choice )
  298. {
  299.     short    menu;
  300.     short    item;
  301.     
  302.     if ( choice )
  303.     {
  304.         menu = HiWord( choice );
  305.         item = LoWord( choice );
  306.         
  307.         switch ( menu )
  308.         {
  309.             case kAppleMenuID:
  310.                 HandleAppleMenu( item );
  311.                 break;
  312.             
  313.             case kFileMenuID:
  314.                 HandleFileMenu( item );
  315.                 break;
  316.         }
  317.     }
  318.     
  319.     HiliteMenu( 0 );
  320. }
  321.  
  322.  
  323.  
  324. /**********************************************************************************************
  325.  * Function Name:  HandleAppleMenu
  326.  *
  327.  * Description:    Standard stuff.
  328.  *
  329.  * Parameters:     item - the menu item selected.
  330.  *
  331.  * Return Value:   None.
  332.  **********************************************************************************************/
  333. void    HandleAppleMenu( short item )
  334. {
  335.     Str255    name;
  336.     
  337.     switch ( item )
  338.     {
  339.         case kAboutItem:
  340.             AboutBox( kAboutTimeOut );
  341.             break;
  342.         
  343.         default:
  344.             GetItem( gAppleMenu, item, name );
  345.             OpenDeskAcc( name );
  346.             break;
  347.     }
  348. }
  349.  
  350.  
  351.  
  352. /**********************************************************************************************
  353.  * Function Name:  HandleFileMenu
  354.  *
  355.  * Description:    Standard stuff.
  356.  *
  357.  * Parameters:     item - the menu item selected.
  358.  *
  359.  * Return Value:   None.
  360.  **********************************************************************************************/
  361. void    HandleFileMenu( short item )
  362. {
  363.     OSType    type;
  364.     FSSpec    file;
  365.     
  366.     // only allow these file types to be processed
  367.     switch ( item )
  368.     {
  369.         case kASCToMac:
  370.         case kDeleteRF:
  371.         case kRot13:
  372.         case kTab2Space:
  373.             type = kTEXTType;
  374.             break;
  375.         
  376.         case kFindOriginal:
  377.         case kTouch:
  378.         case kTypeCreator:
  379.             type = kAnyType;
  380.             break;
  381.     }
  382.     
  383.     if ( item == kQuitItem )
  384.     {
  385.         gQuit = true;
  386.     }
  387.     else if ( item == kPrefsItem )
  388.     {
  389.         ChooseDefault( true );
  390.     }
  391.     else if ( GetFileSpec( &file, type ) == noErr )
  392.     {
  393.         ProcessSerialNumber    psn = { 0, kCurrentProcess };
  394.         AEAddressDesc        address;
  395.         AppleEvent            event;
  396.         AEDescList            docList;
  397.         
  398.         // set the conversion type
  399.         gConversionType = item;
  400.         gFromMenu = true;
  401.         
  402.         // get our address
  403.         AECreateDesc( typeProcessSerialNumber, &psn, sizeof( ProcessSerialNumber ), &address );
  404.         
  405.         // create a new apple event to send to ourselves
  406.         AECreateAppleEvent( kCoreEventClass, kAEOpenDocuments, &address, kAutoGenerateReturnID, kAnyTransactionID, &event );
  407.         
  408.         // create an empty list
  409.         AECreateList( (Ptr)0, (Size)0, false, &docList );
  410.         
  411.         // put the file spec in the list
  412.         AEPutPtr( &docList, 1, typeFSS, &file, sizeof( FSSpec ) );
  413.         
  414.         // put the list in the apple event
  415.         AEPutParamDesc( &event, keyDirectObject, &docList );
  416.         
  417.         // send the event
  418.         AESend( &event, nil, kAEWaitReply, kAENormalPriority, kAEDefaultTimeout, nil, nil );
  419.         
  420.         // clean up
  421.         AEDisposeDesc( &address );
  422.         AEDisposeDesc( &event );
  423.         AEDisposeDesc( &docList );
  424.     }
  425. }
  426.  
  427.  
  428.  
  429. /**********************************************************************************************
  430.  * Function Name:  GetFileSpec
  431.  *
  432.  * Description:    Ask the user for a file.
  433.  *
  434.  * Parameters:     file - the file spec of the file.
  435.  *                 type - the type of file to list (e.g. 'TEXT', '****').
  436.  *
  437.  * Return Value:   noErr if ok, error code otherwise.
  438.  **********************************************************************************************/
  439. OSErr    GetFileSpec( FSSpec *file, OSType type )
  440. {
  441.     OSErr                err = -1;
  442.     Point                where = { 0, 0 };
  443.     SFTypeList            typeList;
  444.     short                numTypes = (type == kAnyType) ? -1 : 1;
  445.     StandardFileReply    reply;
  446.     
  447.     typeList[0] = type;
  448.     
  449.     StandardGetFile( nil, numTypes, typeList, &reply );
  450.     if ( reply.sfGood )
  451.     {
  452.         *file = reply.sfFile;
  453.         err = noErr;
  454.     }
  455.     
  456.     return ( err );
  457. }
  458.  
  459.  
  460.  
  461. /**********************************************************************************************
  462.  * Function Name:  FSpfopen
  463.  *
  464.  * Description:    Open a file from an FSSpec using fopen.
  465.  *
  466.  * Parameters:     spec - the FSSpec containing the info we need.
  467.  *
  468.  * Return Value:   A file pointer to the opened file, nil if error.
  469.  **********************************************************************************************/
  470. FILE    *FSpfopen( FSSpec *spec, char *mode )
  471. {
  472.     short    vRefNum;
  473.     long    parID;
  474.     char    name[64];
  475.     
  476.     short    oldVol;
  477.     FILE    *fp = nil;
  478.     
  479.     vRefNum = spec->vRefNum;
  480.     parID = spec->parID;
  481.     BlockMove( &spec->name[1], name, spec->name[0] );
  482.     name[spec->name[0]] = '¥0';
  483.     
  484.     if ( GetVol( nil, &oldVol ) == noErr )
  485.     {
  486.         if ( HSetVol( nil, vRefNum, parID ) == noErr )
  487.         {
  488.             fp = fopen( name, mode );
  489.         }
  490.         
  491.         SetVol( nil, oldVol );
  492.     }
  493.     
  494.     return ( fp );
  495. }
  496.  
  497.  
  498.  
  499. /**********************************************************************************************
  500.  * Function Name:  TickleParentDir
  501.  *
  502.  * Description:    Update the file's parent directory modification date so changes to the
  503.  *                 file appear immediately.
  504.  *
  505.  * Parameters:     file - a pointer to the FSSpec of the file.
  506.  *
  507.  * Return Value:   None.
  508.  **********************************************************************************************/
  509. void    TickleParentDir( FSSpec *file )
  510. {
  511.     CInfoPBRec    pb;
  512.     
  513.     pb.dirInfo.ioCompletion = 0;
  514.     pb.dirInfo.ioNamePtr = 0;
  515.     pb.dirInfo.ioVRefNum = file->vRefNum;
  516.     pb.dirInfo.ioFDirIndex = -1;
  517.     pb.dirInfo.ioDrDirID = file->parID;
  518.     
  519.     PBGetCatInfoSync( &pb );
  520.     GetDateTime( &pb.dirInfo.ioDrMdDat );
  521.     PBSetCatInfoSync( &pb );
  522. }
  523.  
  524.  
  525.  
  526. /**********************************************************************************************
  527.  * Function Name:  GetFileOSType
  528.  *
  529.  * Description:    Get the file's Finder info and return the type.
  530.  *
  531.  * Parameters:     file - a pointer to the FSSpec of the file.
  532.  *
  533.  * Return Value:   The type of the file.
  534.  **********************************************************************************************/
  535. OSType    GetFileOSType( FSSpec *file )
  536. {
  537.     FInfo    info;
  538.     
  539.     // get the file's Finder info
  540.     FSpGetFInfo( file, &info );
  541.     
  542.     return ( info.fdType );
  543. }
  544.  
  545.  
  546.  
  547. /**********************************************************************************************
  548.  * Function Name:  GetFSSpecType
  549.  *
  550.  * Description:    Determine if an FSSpec is a file or a folder.
  551.  *
  552.  * Parameters:     spec - a file system specification.
  553.  *
  554.  * Return Value:   0 = folder, 1 = file.
  555.  **********************************************************************************************/
  556. short    GetFSSpecType( FSSpec *spec )
  557. {
  558.     CInfoPBRec    pb;
  559.     
  560.     pb.hFileInfo.ioVRefNum = spec->vRefNum;
  561.     pb.hFileInfo.ioDirID = spec->parID;
  562.     pb.hFileInfo.ioNamePtr = spec->name;
  563.     pb.hFileInfo.ioFDirIndex = 0;
  564.     PBGetCatInfoSync( &pb );
  565.     
  566.     // 0 = folder, 1 = file
  567.     return ( ((char)(pb.hFileInfo.ioFlAttrib) & (char)0x10) ? 0 : 1 );
  568. }
  569.  
  570.  
  571.  
  572. /**********************************************************************************************
  573.  * Function Name:  AboutBox
  574.  *
  575.  * Description:    Gimme some credit.
  576.  *
  577.  * Parameters:     hangTime - dismiss the dialog after this many seconds.
  578.  *
  579.  * Return Value:   None.
  580.  **********************************************************************************************/
  581. void    AboutBox( short hangTime )
  582. {
  583.     DialogPtr        aboutBox;
  584.     WindowPtr        saveMe;
  585.     Boolean            done = false;
  586.     short            item;
  587.     ModalFilterUPP    filter = NewModalFilterProc( AboutBoxDlgFltr );
  588.     
  589.     static unsigned char    line0[] = "¥pDonna's word processor file converter";
  590.     static unsigned char    line1[] = "¥p(and other assorted filters)";
  591.     static unsigned char    line2[] = "¥pby Eric V. Curtis (boston84@aol.com)";
  592.     
  593.     if ( aboutBox = GetNewDialog( kAboutBoxDlog, nil, (WindowPtr)-1L ) )
  594.     {
  595.         GetPort( &saveMe );
  596.         SetPort( aboutBox );
  597.         ShowWindow( aboutBox );
  598.         
  599.         TextFont( geneva );
  600.         TextSize( 24 );
  601.         TextFace( bold );
  602.         MoveTo( CenterString( &aboutBox->portRect, gAppName ), 30 );
  603.         DrawString( gAppName );
  604.         
  605.         TextSize( 9 );
  606.         MoveTo( CenterString( &aboutBox->portRect, line0 ), 52 );
  607.         DrawString( line0 );
  608.         MoveTo( CenterString( &aboutBox->portRect, line1 ), 64 );
  609.         DrawString( line1 );
  610.         TextFace( normal );
  611.         MoveTo( CenterString( &aboutBox->portRect, line2 ), 123 );
  612.         DrawString( line2 );
  613.         
  614.         MoveTo( aboutBox->portRect.left + kInset, 106 );
  615.         DrawString( kDate );
  616.         MoveTo( aboutBox->portRect.right - 60 - kInset, 106 );
  617.         DrawString( kVersion );
  618.         
  619.         SetWRefCon( aboutBox, TickCount() + (hangTime * 60) );
  620.         while ( done == false )
  621.         {
  622.             ModalDialog( filter, &item );
  623.             switch( item )
  624.             {
  625.                 case kAboutItem:
  626.                     done = true;
  627.                     break;
  628.             }
  629.         }
  630.         
  631.         SetPort( saveMe );    
  632.         DisposDialog( aboutBox );
  633.     }
  634. }
  635.  
  636.  
  637.  
  638. /**********************************************************************************************
  639.  * Function Name:  AboutBoxDlgFltr
  640.  *
  641.  * Description:    Clicking anywhere or pressing any key dismisses the dialog.
  642.  *
  643.  * Parameters:     dialog - the dialog being filtered.
  644.  *                 event - the event record being processed.
  645.  *                 item - the item in which the event occured.
  646.  *
  647.  * Return Value:   true - Tells ModalDialog to return immediately and not handle the event.
  648.  *                 false - Tells ModalDialog to handle the event normally.
  649.  **********************************************************************************************/
  650. pascal Boolean    AboutBoxDlgFltr( DialogPtr dialog, EventRecord *event, short *item )
  651. {
  652.     Boolean    result = false;
  653.     
  654.     if ( (event->what == keyDown) || (event->what == mouseDown) || (TickCount() >= GetWRefCon( dialog )) )
  655.     {
  656.         *item = kAboutItem;
  657.         result = true;
  658.     }
  659.     
  660.     return ( result );
  661. }
  662.  
  663.  
  664.  
  665. /**********************************************************************************************
  666.  * Function Name:  CenterString
  667.  *
  668.  * Description:    Center a string horizontally in a rectangle.
  669.  *
  670.  * Parameters:     rect - the rectangle.
  671.  *                 string - the string to be centered.
  672.  *
  673.  * Return Value:   the horizontal offset to center the string.
  674.  **********************************************************************************************/
  675. short    CenterString( Rect *rect, Str255 string )
  676. {
  677.     return ( ((rect->right - rect->left - StringWidth( string )) / 2) + 1 );
  678. }
  679.  
  680.  
  681.  
  682. /**********************************************************************************************
  683.  * Function Name:  pstrcat
  684.  *
  685.  * Description:    Catenate two pascal strings.  The first string is replaced with the
  686.  *                 catenation of the first and second strings.  If the total length of both
  687.  *                 strings is more than 255, the second string gets truncated.
  688.  *
  689.  *                 Note:  Str255 is defined as: typedef unsigned char Str255[256].
  690.  *
  691.  * Parameters:     s1, s2 - the pascal strings to catenate.
  692.  *
  693.  * Return Value:   s1 contains the catenation of s1 and s2.
  694.  *                 true if second string was truncated, false otherwise.
  695.  **********************************************************************************************/
  696. Boolean    pstrcat( Str255 s1, Str255 s2 )
  697. {
  698.     Boolean    truncated = false;
  699.     
  700.     // truncate the 2nd string if necessary
  701.     if ( *s1 + *s2 > 255 )
  702.     {
  703.         *s2 = 255 - *s1;
  704.         truncated = true;
  705.     }
  706.     
  707.     // catenate the strings
  708.     BlockMove( s2+1, s1+(*s1)+1, *s2 );
  709.     *s1 += *s2;
  710.     
  711.     return ( truncated );
  712. }
  713.  
  714.  
  715.  
  716. /**********************************************************************************************
  717.  * Function Name:  pstrcpy
  718.  *
  719.  * Description:    Copy the pascal string src to the pascal string dst.
  720.  *
  721.  * Parameters:     dst, src - the destination and source strings.
  722.  *
  723.  * Return Value:   None.
  724.  **********************************************************************************************/
  725. void    pstrcpy( Str255 dst, Str255 src )
  726. {
  727.     BlockMove( src, dst, (*src)+1 );
  728. }
  729.  
  730.  
  731.  
  732. /**********************************************************************************************
  733.  * Function Name:  Cancel
  734.  *
  735.  * Description:    Let the user cancel a conversion in progress.
  736.  *
  737.  * Parameters:     None.
  738.  *
  739.  * Return Value:   true if cancel, false otherwise.
  740.  **********************************************************************************************/
  741. Boolean    Cancel( void )
  742. {
  743.     EventRecord    event;
  744.     Boolean        cancel = false;
  745.     static        doit = 0;
  746.     
  747.     if ( WaitNextEvent( everyEvent, &event, 1, nil ) )
  748.     {
  749.         switch ( event.what )
  750.         {
  751.             case updateEvt:
  752.                 if ( (WindowPtr)event.message == gProgressDlog )
  753.                 {
  754.                     BeginUpdate( gProgressDlog );
  755.                     DrawDialog( gProgressDlog );
  756.                     EndUpdate( gProgressDlog );
  757.                 }
  758.                 break;
  759.             
  760.             case keyDown:
  761.             case autoKey:
  762.                 if ( (event.modifiers & cmdKey) && ((event.message & charCodeMask) == kPeriod) )
  763.                 {
  764.                     cancel = true;
  765.                 }
  766.                 break;
  767.             
  768.             case mouseDown:
  769.                 {
  770.                     WindowPtr    window;
  771.                     if ( FindWindow( event.where, &window ) == inDrag )
  772.                     {
  773.                         DragWindow( window, event.where, &(**GetGrayRgn()).rgnBBox );
  774.                         SaveWindowPrefs( gProgressDlog );
  775.                     }
  776.                 }
  777.                 break;
  778.         }
  779.     }
  780.     
  781.     return ( cancel );
  782. }
  783.  
  784.  
  785.  
  786. /**********************************************************************************************
  787.  * Function Name:  SpinCursor
  788.  *
  789.  * Description:    Spin the cursor while work is being done.
  790.  *
  791.  * Parameters:     None.
  792.  *
  793.  * Return Value:   None.
  794.  **********************************************************************************************/
  795. void    SpinCursor( void )
  796. {
  797.     static short    id = 1;
  798.     CursHandle        cursH;
  799.     
  800.     if ( cursH = (CursHandle)Get1IndResource( kCursorType, id ) )
  801.     {
  802.         HLock( (Handle)cursH );
  803.         SetCursor( *cursH );
  804.         ReleaseResource( (Handle)cursH );
  805.     }
  806.     
  807.     id++;
  808.     if ( id > Count1Resources( kCursorType ) ) id = 1;
  809. }
  810.  
  811.  
  812.  
  813. /**********************************************************************************************
  814.  * Function Name:  ScrollIcon
  815.  *
  816.  * Description:    Scroll the application icon while work is being done.
  817.  *
  818.  * Parameters:     None.
  819.  *
  820.  * Return Value:   None.
  821.  **********************************************************************************************/
  822. void    ScrollIcon( void )
  823. {
  824.     static short    offset = 0;
  825.     WindowPtr        oldPort;
  826.     short            iType;
  827.     Handle            iHandle;
  828.     Rect            iRect;
  829.     RgnHandle        rgnH = NewRgn();
  830.     
  831.     if ( gProgressDlog )
  832.     {
  833.         GetPort( &oldPort );
  834.         SetPort( gProgressDlog );
  835.         GetClip( rgnH );
  836.         
  837.         GetDItem( gProgressDlog, kSpinItem, &iType, &iHandle, &iRect );
  838.         ClipRect( &iRect );
  839.         OffsetRect( &iRect, 0, -offset );
  840.         PlotIconID( &iRect, atNone, ttNone, kBaseResID );
  841.         
  842.         OffsetRect( &iRect, 0, kIconHeight+kIconSpace );
  843.         PlotIconID( &iRect, atNone, ttNone, kBaseResID );
  844.         
  845.         OffsetRect( &iRect, 0, -kIconSpace );
  846.         iRect.bottom = iRect.top + kIconSpace;
  847.         EraseRect( &iRect );
  848.         
  849.         offset++;
  850.         if ( offset > kIconHeight ) offset = 0;
  851.         
  852.         ClipRect( &(**rgnH).rgnBBox );
  853.         DisposeRgn( rgnH );
  854.         SetPort( oldPort );
  855.     }
  856. }
  857.  
  858.  
  859.  
  860. /**********************************************************************************************
  861.  * Function Name:  Progress
  862.  *
  863.  * Description:    Create, update, and destroy the progress dialog.
  864.  *
  865.  * Parameters:     what - what to do.
  866.  *                 remain - how many files to go.
  867.  *                 name - the filename.
  868.  *                 percent - how much to fill the progress bar.
  869.  *
  870.  * Return Value:   None.
  871.  **********************************************************************************************/
  872. void    Progress( short what, short remain, Str255 name, short percent )
  873. {
  874.     WindowPtr        oldPort;
  875.     Rect            tRect;
  876.     Str255            tStr;
  877.     short            iType;
  878.     Handle            iHandle;
  879.     static Rect        iRect, bar;
  880.     static float    limit;
  881.     
  882.     switch ( what )
  883.     {
  884.         case eCreate:
  885.             if ( gProgressDlog )
  886.                 DisposDialog( gProgressDlog );
  887.             
  888.             gProgressDlog = GetNewDialog( kProgressDlog, nil, kMoveToFront );
  889.             if ( gProgressDlog )
  890.             {
  891.                 GetPort( &oldPort );
  892.                 SetPort( gProgressDlog );
  893.                 LoadWindowPrefs( gProgressDlog );
  894.                 ShowWindow( gProgressDlog );
  895.                 
  896.                 GetItem( gFileMenu, gConversionType, tStr );
  897.                 if ( (char)tStr[tStr[0]] == kEllipsis ) tStr[0]--;
  898.                 SetWTitle( gProgressDlog, tStr );
  899.                 
  900.                 GetDItem( gProgressDlog, kRemainItem, &iType, &iHandle, &tRect );
  901.                 NumToString( remain, tStr );
  902.                 SetIText( iHandle, tStr );
  903.                 
  904.                 GetDItem( gProgressDlog, kProgBarItem, &iType, &iHandle, &iRect );
  905.                 SetDItem( gProgressDlog, kProgBarItem, iType, (Handle)&FrameBar, &iRect );
  906.                 bar = iRect;
  907.                 limit = (float)(bar.right - bar.left) / 100.0;
  908.                 InsetRect( &bar, 1, 1 );
  909.                 bar.right = bar.left;
  910.                 SetWRefCon( gProgressDlog, (long)&bar );
  911.                 
  912.                 DrawDialog( gProgressDlog );
  913.                 SetPort( oldPort );
  914.             }
  915.             break;
  916.             
  917.         case eFileName:
  918.             if ( gProgressDlog )
  919.             {
  920.                 GetPort( &oldPort );
  921.                 SetPort( gProgressDlog );
  922.                 GetDItem( gProgressDlog, kFileNameItem, &iType, &iHandle, &tRect );
  923.                 SetIText( iHandle, name );
  924.                 SetPort( oldPort );
  925.             }
  926.             break;
  927.             
  928.         case eRemainPercent:
  929.             if ( gProgressDlog )
  930.             {
  931.                 GetPort( &oldPort );
  932.                 SetPort( gProgressDlog );
  933.                 GetDItem( gProgressDlog, kRemainItem, &iType, &iHandle, &tRect );
  934.                 NumToString( remain, tStr );
  935.                 SetIText( iHandle, tStr );
  936.                 if ( percent < 0 )   percent = 0;
  937.                 if ( percent > 100 ) percent = 100;
  938.                 bar.right = bar.left + (percent * limit);
  939.                 if ( bar.right >= iRect.right )    bar.right = iRect.right-1;
  940.                 FillRect( &bar, &qd.gray );
  941.                 SetPort( oldPort );
  942.             }
  943.             break;
  944.             
  945.         case eDelete:
  946.             if ( gProgressDlog )
  947.             {
  948.                 HideWindow( gProgressDlog );
  949.                 DisposDialog( gProgressDlog );
  950.                 gProgressDlog = 0;
  951.             }
  952.             break;
  953.     }
  954. }
  955.  
  956.  
  957.  
  958. /**********************************************************************************************
  959.  * Function Name:  FrameBar
  960.  *
  961.  * Description:    Draw the progress bar when it needs updating.
  962.  *
  963.  * Parameters:     Standard stuff.
  964.  *
  965.  * Return Value:   None.
  966.  **********************************************************************************************/
  967. pascal void    FrameBar( WindowPtr dialog, short item )
  968. {
  969.     short    iType;
  970.     Handle    iHandle;
  971.     Rect    iRect;
  972.     
  973.     GetDItem( dialog, item, &iType, &iHandle, &iRect );
  974.     FrameRect( &iRect );
  975.     
  976.     FillRect( (Rect *)GetWRefCon( dialog ), &qd.gray );
  977. }
  978.  
  979.  
  980.  
  981. /**********************************************************************************************
  982.  * Function Name:  LoadWindowPrefs
  983.  *
  984.  * Description:    Move the progress dialog into position.
  985.  *
  986.  * Parameters:     window - the window to be moved.
  987.  *
  988.  * Return Value:   None.
  989.  **********************************************************************************************/
  990. void    LoadWindowPrefs( WindowPtr window )
  991. {
  992.     Point    **locationH;
  993.     
  994.     if ( locationH = (Point **)GetResource( 'Pref', kBaseResID+1 ) )
  995.     {
  996.         if ( PtInRect( **locationH, &(**GetGrayRgn()).rgnBBox ) )
  997.         {
  998.             MoveWindow( window, (**locationH).h, (**locationH).v, true );
  999.         }
  1000.         ReleaseResource( (Handle)locationH );
  1001.     }
  1002. }
  1003.  
  1004.  
  1005.  
  1006. /**********************************************************************************************
  1007.  * Function Name:  SaveWindowPrefs
  1008.  *
  1009.  * Description:    Remember the progress dialog's position.
  1010.  *
  1011.  * Parameters:     window - the window of interest.
  1012.  *
  1013.  * Return Value:   None.
  1014.  **********************************************************************************************/
  1015. void    SaveWindowPrefs( WindowPtr window )
  1016. {
  1017.     Point        **locationH, topLeft;
  1018.     WindowPtr    oldPort;
  1019.     
  1020.     if ( locationH = (Point **)GetResource( 'Pref', kBaseResID+1 ) )
  1021.     {
  1022.         GetPort( &oldPort );
  1023.         SetPort( window );
  1024.         topLeft = *(Point *)&window->portRect;
  1025.         LocalToGlobal( &topLeft );
  1026.         if ( ((**locationH).h != topLeft.h) || ((**locationH).v != topLeft.v) )
  1027.         {
  1028.             **locationH = topLeft;
  1029.             ChangedResource( (Handle)locationH );
  1030.         }
  1031.         ReleaseResource( (Handle)locationH );
  1032.         SetPort( oldPort );
  1033.     }
  1034. }
  1035.  
  1036.  
  1037.  
  1038. /**********************************************************************************************
  1039.  * Function Name:  ChooseDefault
  1040.  *
  1041.  * Description:    Let the user set the default filter to be used.
  1042.  *
  1043.  * Parameters:     save - true for perm, false for temp.
  1044.  *
  1045.  * Return Value:   noErr if ok, error code if canceled.
  1046.  **********************************************************************************************/
  1047. OSErr    ChooseDefault( Boolean save )
  1048. {
  1049.     OSErr            err = noErr;
  1050.     DialogPtr        picker;
  1051.     WindowPtr        saveMe;
  1052.     Boolean            done = false;
  1053.     short            item;
  1054.     ModalFilterUPP    filter = NewModalFilterProc( ChooseDefaultDlgFltr );
  1055.     
  1056.     short            i;
  1057.     short            iType;
  1058.     Handle            iHandle;
  1059.     Rect            iRect;
  1060.     Str255            str;
  1061.     long            ticks;
  1062.     
  1063.     if ( picker = GetNewDialog( kDefaultDlog, nil, (WindowPtr)-1L ) )
  1064.     {
  1065.         GetPort( &saveMe );
  1066.         SetPort( picker );
  1067.         ShowWindow( picker );
  1068.         
  1069.         // draw a divider line
  1070.         GetDItem( picker, kDivider, &iType, &iHandle, &iRect );
  1071.         FrameRect( &iRect );
  1072.         
  1073.         // de-activate and name each radio button
  1074.         for ( i = kASCToMac+2; i <= kTypeCreator+2; i++ )
  1075.         {
  1076.             GetDItem( picker, i, &iType, &iHandle, &iRect );
  1077.             SetCtlValue( (ControlHandle)iHandle, 0 );
  1078.             
  1079.             GetItem( gFileMenu, i-2, str );
  1080.             if ( (char)(str[str[0]]) == kEllipsis ) str[0]--;
  1081.             SetCTitle( (ControlHandle)iHandle, str );
  1082.         }
  1083.         
  1084.         // activate the radio button of the currently selected filter
  1085.         gConversionType = LoadFilterPrefs();
  1086.         GetDItem( picker, gConversionType+2, &iType, &iHandle, &iRect );
  1087.         SetCtlValue( (ControlHandle)iHandle, 1 );
  1088.         
  1089.         while ( !done )
  1090.         {
  1091.             ModalDialog( filter, &item );
  1092.             switch( item )
  1093.             {
  1094.                 case -1:    // -1 + 1 =  0, ok
  1095.                 case -2:    // -2 + 1 = -1, cancel
  1096.                     err = item + 1;
  1097.                     done = true;
  1098.                     break;
  1099.                 
  1100.                 default:
  1101.                     // adjust the radio buttons
  1102.                     GetDItem( picker, gConversionType+2, &iType, &iHandle, &iRect );
  1103.                     SetCtlValue( (ControlHandle)iHandle, 0 );
  1104.                     GetDItem( picker, item, &iType, &iHandle, &iRect );
  1105.                     SetCtlValue( (ControlHandle)iHandle, 1 );
  1106.                     Delay( 6, &ticks );
  1107.                     
  1108.                     // remember the new filter index
  1109.                     gConversionType = item-2;
  1110.                     if ( save ) SaveFilterPrefs( gConversionType );
  1111.                     
  1112.                     done = true;
  1113.                     break;
  1114.             }
  1115.         }
  1116.         
  1117.         SetPort( saveMe );    
  1118.         DisposDialog( picker );
  1119.     }
  1120.     
  1121.     return ( err );
  1122. }
  1123.  
  1124.  
  1125.  
  1126. /**********************************************************************************************
  1127.  * Function Name:  ChooseDefaultDlgFltr
  1128.  *
  1129.  * Description:    Handle mouse and keystrokes.
  1130.  *
  1131.  * Parameters:     dialog - the dialog being filtered.
  1132.  *                 event - the event record being processed.
  1133.  *                 item - the item in which the event occured.
  1134.  *
  1135.  * Return Value:   true - ModalDialog returns immediately and without handling the event.
  1136.  *                 false - ModalDialog handles the event normally.
  1137.  **********************************************************************************************/
  1138. pascal Boolean    ChooseDefaultDlgFltr( DialogPtr dialog, EventRecord *event, short *item )
  1139. {
  1140. #pragma unused ( dialog )
  1141.     char    c;
  1142.     Boolean    result = false;
  1143.     
  1144.     if ( (event->what == keyDown) || (event->what == autoKey) )
  1145.     {
  1146.         c = event->message & charCodeMask;
  1147.         
  1148.         if ( (c == kEnter) || (c == kReturn) )
  1149.         {
  1150.             *item = -1;
  1151.             result = true;
  1152.         }
  1153.         
  1154.         if ( (c == kEscape) || ((event->modifiers & cmdKey) && (c == kPeriod)) )
  1155.         {
  1156.             *item = -2;
  1157.             result = true;
  1158.         }
  1159.         
  1160.         if ( (c >= '0'+kASCToMac) && (c <= '0'+kTypeCreator) )
  1161.         {
  1162.             *item = c - '0' + 2;
  1163.             result = true;
  1164.         }
  1165.     }
  1166.     
  1167.     return ( result );
  1168. }
  1169.  
  1170.  
  1171.  
  1172. /**********************************************************************************************
  1173.  * Function Name:  LoadFilterPrefs
  1174.  *
  1175.  * Description:    Get the default conversion type.
  1176.  *
  1177.  * Parameters:     None.
  1178.  *
  1179.  * Return Value:   pref - the default conversion type index.
  1180.  **********************************************************************************************/
  1181. char    LoadFilterPrefs( void )
  1182. {
  1183.     char    **prefH, pref = 1;
  1184.     
  1185.     if ( prefH = (char **)Get1Resource( kPrefType, kBaseResID ) )
  1186.     {
  1187.         pref = **prefH;
  1188.         ReleaseResource( (Handle)prefH );
  1189.     }
  1190.     
  1191.     return ( pref );
  1192. }
  1193.  
  1194.  
  1195.  
  1196. /**********************************************************************************************
  1197.  * Function Name:  SaveFilterPrefs
  1198.  *
  1199.  * Description:    Set the default conversion type.
  1200.  *
  1201.  * Parameters:     pref - the default conversion type index.
  1202.  *
  1203.  * Return Value:   None.
  1204.  **********************************************************************************************/
  1205. void    SaveFilterPrefs( char pref )
  1206. {
  1207.     char    **prefH;
  1208.     
  1209.     if ( prefH = (char **)Get1Resource( kPrefType, kBaseResID ) )
  1210.     {
  1211.         **prefH = pref;
  1212.         ChangedResource( (Handle)prefH );
  1213.         WriteResource( (Handle)prefH );
  1214.         ReleaseResource( (Handle)prefH );
  1215.     }
  1216. }
  1217.  
  1218.  
  1219.  
  1220. /**********************************************************************************************
  1221.  * Function Name:  SpecialKeyDown
  1222.  *
  1223.  * Description:    Check to see if a certain key is down.
  1224.  *
  1225.  * Parameters:     key - a key code.
  1226.  *
  1227.  * Return Value:   true if key is down, false otherwise.
  1228.  **********************************************************************************************/
  1229. Boolean    SpecialKeyDown( unsigned short key )
  1230. {
  1231.     KeyMap            km;
  1232.     unsigned char    *akm = (unsigned char *)&km;
  1233.     
  1234.     GetKeys( km );
  1235.     return ( (akm[key>>3] >> (key & 7)) & 1 );
  1236. }
  1237.